﻿using Core.FrameWork.Commons.App;
using Core.FrameWork.Commons.Extensions;
using Core.FrameWork.Commons.Loging.Model;
using Core.FrameWork.Commons.Loging.Storage;
using Masuit.Tools;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace Core.FrameWork.Commons.Loging
{
    /// <summary>
    /// 日志锁
    /// </summary>
    public class LogLockHelper
    {
        /// <summary>
        /// 日志存储
        /// </summary>
        private static ILogStorage logStorage;
        /// <summary>
        /// 读写锁
        /// </summary>
        private static ReaderWriterLockSlim LogWriteLock;
        /// <summary>
        /// 写入总次数
        /// </summary>
        private static int WritedCount;
        /// <summary>
        /// 失败总次数
        /// </summary>
        static int FailedCount;
        /// <summary>
        /// 批量写入次数
        /// </summary>
        private static int BatchCount;
        /// <summary>
        /// 批量存储字典数据
        /// </summary>
        private static Dictionary<string, string[]> dict;
        static LogLockHelper()
        {
            //默认实现为 写入本地文件
            logStorage = new FileStorage();
            //读写锁
            LogWriteLock = new ReaderWriterLockSlim();
            //设置批量写入次数
            BatchCount = 30;
            //初始化批量存储字典
            dict = new Dictionary<string, string[]>();
        }
        /// <summary>
        /// 读取失败次数
        /// </summary>
        /// <returns></returns>
        public static int ReadFailedCount()
        {
            return FailedCount;
        }
        /// <summary>
        /// 读取总写入次数
        /// </summary>
        /// <returns></returns>
        public static int ReadWritedCount()
        {
            return WritedCount;
        }
        /// <summary>
        /// 写入文件
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="filename"></param>
        /// <param name="dataParas"></param>
        /// <param name="IsHeader"></param>
        public static void WriteLog(string rootPath, string filename, string[] dataParas, bool IsHeader = true)
        {
            try
            {
                //设置读写锁为写入模式独占资源，其他写入请求需要等待本次写入结束之后才能继续写入
                LogWriteLock.EnterWriteLock();

                logStorage.WriteLog(rootPath, filename, dataParas, IsHeader);
                WritedCount++;
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
                FailedCount++;
            }
            finally
            {
                //退出写入模式，释放资源占用
                //注意：一次请求对应一次释放
                //      若释放次数大于请求次数将会触发异常[写入锁定未经保持即被释放]
                //      若请求处理完成后未释放将会触发异常[此模式不下允许以递归方式获取写入锁定]
                LogWriteLock.ExitWriteLock();
            }
        }
        /// <summary>
        /// 批量写入文件
        /// </summary>
        /// <param name="rootPath"></param>
        /// <param name="filename"></param>
        /// <param name="dataParas"></param>
        /// <param name="IsHeader"></param>
        public static void WriteLogBatch(string rootPath, string filename, string[] dataParas, bool IsHeader = true)
        {
            try
            {
                //设置读写锁为写入模式独占资源，其他写入请求需要等待本次写入结束之后才能继续写入
                LogWriteLock.EnterWriteLock();

                //待写入的数据
                List<string> batchData = new List<string>();

                var contains = dict.Where(s => s.Key.Contains(rootPath));

                //小于批量写入次数
                if (contains.Count() <= BatchCount)
                {
                    dict.Add(filename + dict.Count(), dataParas);
                    return;
                }

                foreach (var item in contains)
                {
                    //删除待写入的data
                    dict.Remove(item.Key);
                    batchData.AddRange(item.Value);
                }

                logStorage.WriteLog(rootPath, filename, batchData.ToArray(), IsHeader);
                WritedCount++;
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
                FailedCount++;
            }
            finally
            {
                //退出写入模式，释放资源占用
                //注意：一次请求对应一次释放
                //      若释放次数大于请求次数将会触发异常[写入锁定未经保持即被释放]
                //      若请求处理完成后未释放将会触发异常[此模式不下允许以递归方式获取写入锁定]
                LogWriteLock.ExitWriteLock();
            }
        }
        /// <summary>
        /// 读取日志
        /// </summary>
        /// <param name="Path"></param>
        /// <param name="encode"></param>
        /// <returns></returns>
        public static string ReadLog(string Path, Encoding encode)
        {
            string json = "";
            try
            {
                LogWriteLock.EnterReadLock();

                //读取文件
                json = logStorage.ReadLog(Path, encode);
            }
            catch (Exception ex)
            {
                NLogUtil.WriteAll(NLog.LogLevel.Error, LogType.Web, "接口读取日志错误", $"读取路径:【{Path}】", new Exception("接口读取日志错误", ex));
                FailedCount++;
            }
            finally
            {
                LogWriteLock.ExitReadLock();
            }
            return json;
        }
    }
}
